//-----------------------------------------------------------------------------
//  Galv's Cam Control
//-----------------------------------------------------------------------------
//  For: RPGMAKER MV
//  GALV_CamControl.js
//-----------------------------------------------------------------------------
//  2015-12-30 - Version 1.7 - another fix for shuttering issue
//  2015-12-17 - Version 1.6 - put in code to fix potential shuttering issue
//  2015-12-17 - Version 1.5 - fixed an issue that enabled the disabled cam
//  2015-12-01 - Version 1.4 - minor code changes
//  2015-12-01 - Version 1.3 - missed part of the last bug. Fixed now.
//  2015-11-30 - Version 1.2 - fixed bug with loading game and target breaking
//  2015-11-27 - Version 1.1 - added tile size option
//  2015-11-27 - Version 1.0 - release
//-----------------------------------------------------------------------------
// Terms can be found at:
// galvs-scripts.com
//-----------------------------------------------------------------------------

var Imported = Imported || {};
Imported.Galv_CamControl = true;

var Galv = Galv || {};          // Galv's main object
Galv.pCmd = Galv.pCmd || {};    // Plugin Command manager
Galv.CC = Galv.CC || {};        // Galv's stuff

//-----------------------------------------------------------------------------
/*:
 * @plugindesc 鏡頭焦點調整插件
 * 
 * @author Galv - galvs-scripts.com
 *
 * @param Tile Size
 * @desc 預設 48. 可以自行調整嘗試
 * @default 48
 *
 * @help
 *   Galv's Cam Control
 * ----------------------------------------------------------------------------
 * This plugin creates a sliding movement for the camera as well as allows you
 * to set the target position of it to wherever required. (Player, event, xy)
 *
 * ----------------------------------------------------------------------------
 *   PLUGIN COMMANDS
 * ----------------------------------------------------------------------------
 *   CAM PLAYER SPD               // 鏡頭焦點設置在玩家身上
 *                                // CAM - 這插件的開頭文字
 *                                // PLAYER - 插件特殊用法指定玩家
 *                                // SPD    - 鏡頭滑動速度
 *                                //          v# 可以使用變數
 *                                //          預設速度 800
 *                                //          可以留空忽略
 *
 *   CAM EVENT ID SPD             // 鏡頭焦點設置在事件上
 *                                // CAM - 這插件的開頭文字
 *                                // EVENT  - 插件特殊用法指定事件
 *                                // ID     - 輸入事件ID
 *                                //          v# 可以使用變數
 *                                // SPD    - 鏡頭滑動速度
 *                                //          v# 可以使用變數
 *                                //          預設速度 800
 *                                //          可以留空忽略
 *
 *   CAM X Y SPD                  // 鏡頭焦點設置在 x,y 座標
 *                                // CAM - 這插件的開頭文字
 *                                // X      - 地圖上的 X座標
 *                                // Y      - 地圖上的 Y座標
 *                                //          v# 可以使用變數
 *                                // SPD    - 鏡頭滑動速度
 *                                //          v# 可以使用變數
 *                                //          預設速度 800
 *                                //          可以留空忽略
 *
 *   CAM DISABLE                  // 關閉玩家走路滑動
 *                                // 使用 CAM ENABLE 開啟滑動效果,CAM PLAYER亦可
 *
 * SPD 為速度 數值愈大 速度愈慢
 * 不建議太快.
 *
 * EXAMPLES
 * CAM PLAYER         // 設置焦點在玩家 預設速度800
 * CAM PLAYER 1600    // 設置焦點在玩家 預設速度1600 (慢)
 * CAM EVENT 3        // 設置焦點在事件3 速度800
 * CAM EVENT 12 400   // C設置焦點在事件12 速度400 (快)
 * CAM 23 18          // 設置焦點於該地圖座標 23,18
 */



//-----------------------------------------------------------------------------
//  CODE STUFFS
//-----------------------------------------------------------------------------

(function() {

Galv.CC.size = Number(PluginManager.parameters('Galv_CamControl')["Tile Size"]);

// OVERWRITE - BECAUSE OF JITTER
Game_Map.prototype.displayX = function() {return Math.round(this._displayX * Galv.CC.size) / Galv.CC.size};
Game_Map.prototype.displayY = function() {return Math.round(this._displayY * Galv.CC.size) / Galv.CC.size};


// GALV'S PLUGIN MANAGEMENT. INCLUDED IN ALL GALV PLUGINS THAT HAVE PLUGIN COMMAND CALLS, BUT ONLY RUN ONCE.
if (!Galv.aliased) {
	var Galv_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
	Game_Interpreter.prototype.pluginCommand = function(command, args) {
		if (Galv.pCmd[command]) {
			Galv.pCmd[command](args);
			return;
		};
		Galv_Game_Interpreter_pluginCommand.call(this, command, args);
	};
	Galv.aliased = true; // Don't keep aliasing for other Galv scripts.
};

// Direct to Plugin Object
Galv.pCmd.CAM = function(arguments) {
	Galv.CC.camControl(arguments);
};
// END GALV'S PLUGIN MANAGEMENT


Galv.CC.camControl = function(args) {
	
	var key = args[0].toLowerCase();
	var speed = 800;
	switch (key) {
		case "player":
			var target = $gamePlayer;
			if (args[1]) speed = Galv.CC.getValue(args[1]);
			break;
		case "event":
			var eId = Galv.CC.getValue(args[1]);
			var target = $gameMap.event(eId);
			if (args[2]) speed = Galv.CC.getValue(args[2]);
			break;
		case "disable":
			$gameMap.camTarget = $gamePlayer;
			$gameMap.camNorm = true;
			$gameMap.savedCamTarget = null;
			return;
		case "enable":
			$gameMap.camTarget = $gamePlayer;
			$gameMap.camNorm = false;
			$gameMap.savedCamTarget = null;
			return;
		default:
			var px = Galv.CC.getValue(args[0]);
			var py = Galv.CC.getValue(args[1]);
			if (args[2]) speed = Galv.CC.getValue(args[2]);
			var target = {
				x: px,
				y: py,
				_realX: px,
				_realY: py,
				screenX: Game_CharacterBase.prototype.screenX,
				screenY: function() {
					var th = $gameMap.tileHeight();
					return Math.round(this.scrolledY() * th + th);
				},
				scrolledX: Game_CharacterBase.prototype.scrolledX,
				scrolledY: Game_CharacterBase.prototype.scrolledY
			};
	};
	
	$gameMap.camTargetSet(target,speed);
	$gameMap.savedCamTarget = args;
};

Galv.CC.getValue = function(string) {
	if (string[0].toLowerCase() === "v") {
		// Use variable
		var varId = Number(string.replace("v",""));
		return $gameVariables.value(varId);
	} else {
		return Number(string);
	};
};


// GAME PLAYER

var Galv_Game_Player_updateScroll = Game_Player.prototype.updateScroll;
Game_Player.prototype.updateScroll = function(lastScrolledX, lastScrolledY) {
	if ($gameMap.camNorm) return Galv_Game_Player_updateScroll.call(this,lastScrolledX, lastScrolledY);
};


// GAME MAP

var Galv_Scene_Map_onMapLoaded = Scene_Map.prototype.onMapLoaded;
Scene_Map.prototype.onMapLoaded = function() {
	Galv_Scene_Map_onMapLoaded.call(this);
	if (!$gameMap.camNorm) {
		$gameMap.savedCamTarget = $gameMap.savedCamTarget || ["PLAYER"];
		Galv.CC.camControl($gameMap.savedCamTarget);
	};
};

var Galv_Game_Map_setup = Game_Map.prototype.setup;
Game_Map.prototype.setup = function(mapId) {
	if (!this.camNorm) {
		this.camTargetSet($gamePlayer,800);
		this.savedCamTarget = ["PLAYER"];
	};
	Galv_Game_Map_setup.call(this,mapId);
};

Game_Map.prototype.camTargetSet = function(target,speed) {
    this.camTarget = target;
    this.camNorm = false;
    this.camSpeed = speed || 800;
};


var Galv_Game_Map_updateScroll = Game_Map.prototype.updateScroll;
Game_Map.prototype.updateScroll = function() {
	if (this.camNorm) return Galv_Game_Map_updateScroll.call(this);

	this._scrollRest = 0;

    var cw = (Graphics.boxWidth / 2);
    var ch = (Graphics.boxHeight / 2);
    
	var screenX = this.camTarget.screenX();
	var screenY = this.camTarget.screenY();
	
    var sx = 0.016 + Math.abs(screenX - cw) / this.camSpeed;
    var sy = 0.016 + Math.abs(screenY - ch) / this.camSpeed;
	//var sx = Math.abs(screenX - cw) / this.camSpeed;
	//var sy = Math.abs(screenY - ch) / this.camSpeed;
    var x_pos = screenX;
    var y_pos = screenY;
	
    if (y_pos + 0.016 < ch) {
      this.scrollUp(sy);
	} else if (y_pos - 0.016 > ch) {
      this.scrollDown(sy);
	};
	
    if (x_pos + 0.016 < cw) {
      this.scrollLeft(sx);
	} else if (x_pos - 0.016 > cw) {
      this.scrollRight(sx);
	};
};

})();